﻿using Microsoft.Extensions.Caching.Distributed;
using Newtonsoft.Json;
using ShenNius.Caches;
using ShenNius.Repository;
using ShenNius.Wechat.API.Domain.Entity;
using ShenNius.Wechat.API.Dtos;
using ShenNius.Wechat.API.Infrastructure.Common;
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Threading.Tasks;

namespace ShenNius.Wechat.API
{
    public class WxBaseService
    {
        private readonly IDistributedCache _cacheHelper;
        private readonly HttpHelper _httpHelper;
        private readonly IBaseRepository<Setting> _repository;

        public WxBaseService(IDistributedCache cacheHelper, HttpHelper httpHelper, IBaseRepository<Setting> repository)
        {
            _cacheHelper = cacheHelper;
            _httpHelper = httpHelper;
            _repository = repository;
        }
        public async Task<string> GetAccessTokenAsync(int id)
        {
            var settingModel = await _repository.GetModelAsync(m => m.Id == id);
            if (settingModel == null)
            {
                throw new ArgumentNullException("当前公众号信息查询为空！");
            }
            return await GetAccessTokenAsync(settingModel.AppId, settingModel.AppSecret);
        }
        /// <summary>
        /// 获得Access_token
        /// </summary>
        /// <param name="appid"></param>
        /// <param name="secret"></param>
        /// <returns></returns>
        public async Task<string> GetAccessTokenAsync(string appid, string secret)
        {
            var model = new AccessTokenOutput();
            var cacheAccess = _cacheHelper.Get<AccessTokenOutput>(WechatCacheKey.AccessToken);
            if (cacheAccess != null)
            {
                model = cacheAccess;
            }
            else
            {
                var url = string.Format("https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={0}&secret={1}", appid, secret);
                model = await _httpHelper.GetAsync<AccessTokenOutput>(url);
                _cacheHelper.Set(WechatCacheKey.AccessToken, model, TimeSpan.FromMinutes(119));
            }
            if (string.IsNullOrEmpty(model.AccessToken))
            {
                throw new ArgumentNullException(nameof(model.AccessToken));
            }
            return model.AccessToken;
        }

        /// <summary>
        /// 同步到公众号的菜单
        /// </summary>
        /// <returns></returns>
        public async Task<WxResult> PushMenu(string accessToken, string body)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/menu/create?access_token={0}", accessToken);
            return await _httpHelper.PostAsync<WxResult>(url, body);
        }
        /// <summary>
        /// 获得素材列表
        /// </summary>
        /// <returns></returns>
        public async Task<MeterList> GetMediaList(string accessToken)
        {
            var url = string.Format("https://api.weixin.qq.com/cgi-bin/material/batchget_material?access_token={0}", accessToken);
            return await _httpHelper.PostAsync<MeterList>(url, "{\"type\":\"news\",\"offset\":0,\"count\":50}");
        }

        /// <summary>
        /// 服务号：上传多媒体文件
        /// </summary>
        /// <param name="accesstoken">调用接口凭据</param>
        /// <param name="filename">文件路径</param>
        /// <param name="contenttype">文件Content-Type类型(例如：image/jpeg、audio/mpeg)</param>
        /// <returns></returns>
        public MeterUploadResult UploadFile(string accessToken, string path, string fileExt)
        {
            string url = string.Format("https://api.weixin.qq.com/cgi-bin/material/add_material?access_token={0}&type={1}", accessToken, "image");

            //文件后缀名，使用格式
            var contenttype = "image/jpeg";
            switch (fileExt)
            {
                case ".png":
                    contenttype = "image/png";
                    break;
            }
            FileStream fs = null;
            byte[] byteArr = null;
            //判断是否网络图片
            if (path.ToLower().StartsWith("http") || path.ToLower().StartsWith("https"))
            {
                WebClient mywebclient = new WebClient();
                byteArr = mywebclient.DownloadData(path);
            }
            else
            {
                fs = new FileStream(path, FileMode.Open, FileAccess.Read);
                byteArr = new byte[fs.Length];
                fs.Read(byteArr, 0, byteArr.Length);
            }
            // 设置参数
            HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;
            CookieContainer cookieContainer = new CookieContainer();
            request.CookieContainer = cookieContainer;
            request.AllowAutoRedirect = true;
            request.Method = "POST";
            string boundary = DateTime.Now.Ticks.ToString("X"); // 随机分隔线
            request.ContentType = "multipart/form-data;charset=utf-8;boundary=" + boundary;
            byte[] itemBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "\r\n");
            byte[] endBoundaryBytes = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
            int pos = path.LastIndexOf("\\");
            string fileName = path.Substring(pos + 1);

            //组织表单数据
            StringBuilder sbHeader = new StringBuilder();
            sbHeader.Append("--" + boundary + "\r\n");
            sbHeader.Append("Content-Disposition: form-data; name=\"media\"; filename=\"" + Guid.NewGuid().ToString() + ".jpg\"; filelength=\"" + byteArr.Length + "\"");
            sbHeader.Append("\r\n");
            sbHeader.Append("Content-Type: " + contenttype);
            sbHeader.Append("\r\n\r\n");

            //请求头部信息 
            //StringBuilder sbHeader = new StringBuilder(string.Format("Content-Disposition:form-data;name=\"file\";filename=\"{0}\"\r\nContent-Type:application/octet-stream\r\n\r\n", fileName));
            byte[] postHeaderBytes = Encoding.UTF8.GetBytes(sbHeader.ToString());
            Stream postStream = request.GetRequestStream();
            postStream.Write(itemBoundaryBytes, 0, itemBoundaryBytes.Length);
            postStream.Write(postHeaderBytes, 0, postHeaderBytes.Length);
            postStream.Write(byteArr, 0, byteArr.Length);
            postStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
            postStream.Close();

            if (fs != null)
            {
                fs.Close();
                fs.Dispose();
            }
            //发送请求并获取相应回应数据
            HttpWebResponse response = request.GetResponse() as HttpWebResponse;
            //直到request.GetResponse()程序才开始向目标网页发送Post请求
            Stream instream = response.GetResponseStream();
            StreamReader sr = new StreamReader(instream, Encoding.UTF8);
            //返回结果网页（html）代码
            string content = sr.ReadToEnd();
            if (content.Contains("errcode"))
            {
                return new MeterUploadResult() { Code = 500 };
            }
            return JsonConvert.DeserializeObject<MeterUploadResult>(content);
        }

    }
}
